h3 라이브러리를 활용한 Uber Data 분석
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from h3 import h3
from collections import Counter
import pydeck as pdk
# 한글 폰트 사용을 위해서 세팅
from matplotlib import font_manager, rc, rcParams
font_path = "C:/Windows/Fonts/malgun.ttf"
font = font_manager.FontProperties(fname = font_path).get_name()
rc('font' , family = font)
# 마이너스 깨짐 현상 해결
rcParams['axes.unicode_minus' ] = False
H3_HEX_DATA = "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/sf.h3cells.json"
df = pd.read_json(H3_HEX_DATA)
df.head()
0
88283082b9fffff
96
1
8828308281fffff
534
2
88283082d7fffff
36
3
88283082c1fffff
297
4
88283082a9fffff
147
def h3_to_lat_lon(h3_address):
lat_lon = h3.h3_to_geo(h3_address)
return lat_lon
def lat_lon_to_h3(lat, lon):
h3_address = h3.geo_to_h3(lat, lon, resolution = 6 ) # resolution : 해상도
return h3_address
df['lat_lon' ] = df['hex' ].apply (h3_to_lat_lon)
df.head()
0
4/1/2014 0:11:00
40.7690
-73.9549
B02512
2014-04-01 00:11:00
Tuesday
0
862a100d7ffffff
(40.74274905936817, -73.95762841287764)
1
4/1/2014 0:17:00
40.7267
-74.0345
B02512
2014-04-01 00:17:00
Tuesday
0
862a1072fffffff
(40.7041679083504, -74.01600847979245)
2
4/1/2014 0:21:00
40.7316
-73.9873
B02512
2014-04-01 00:21:00
Tuesday
0
862a100d7ffffff
(40.74274905936817, -73.95762841287764)
3
4/1/2014 0:28:00
40.7588
-73.9776
B02512
2014-04-01 00:28:00
Tuesday
0
862a100d7ffffff
(40.74274905936817, -73.95762841287764)
4
4/1/2014 0:33:00
40.7594
-73.9722
B02512
2014-04-01 00:33:00
Tuesday
0
862a100d7ffffff
(40.74274905936817, -73.95762841287764)
# Define a layer to display on a map
layer = pdk.Layer(
"H3HexagonLayer" ,
df,
pickable= True ,
stroked= True ,
filled= True ,
extruded= False ,
get_hexagon= "hex" ,
get_fill_color= "[255 - count, 255, count]" ,
get_line_color= [255 , 255 , 255 ],
line_width_min_pixels= 2 ,
)
# Set the viewport location
view_state = pdk.ViewState(latitude= 37.7749295 , longitude=- 122.4194155 , zoom= 14 , bearing= 0 , pitch= 30 )
# Render
r = pdk.Deck(layers= [layer], initial_view_state= view_state, tooltip= {"text" : "Count: {count} " })
r.show()
# 데이터 로드
df = pd.read_csv('https://github.com/fivethirtyeight/uber-tlc-foil-response/raw/master/uber-trip-data/uber-raw-data-apr14.csv' )
# 데이터셋 확인
print (df.head())
Date/Time Lat Lon Base
0 4/1/2014 0:11:00 40.7690 -73.9549 B02512
1 4/1/2014 0:17:00 40.7267 -74.0345 B02512
2 4/1/2014 0:21:00 40.7316 -73.9873 B02512
3 4/1/2014 0:28:00 40.7588 -73.9776 B02512
4 4/1/2014 0:33:00 40.7594 -73.9722 B02512
Date/Time : 여행이 시작된 날짜와 시간 정보. 예를 들어, 4/1/2014 0:11:00는 2014년 4월 1일 오전 0시 11분에 시작된 여행을 의미합니다.
Lat : 출발지의 위도 정보. 위도는 지구의 남북 위치를 나타내는 수치입니다.
Lon : 출발지의 경도 정보. 경도는 지구의 동서 위치를 나타내는 수치입니다.
Base : Uber의 서비스를 제공하는 특정 “베이스 코드”가 포함되어 있습니다. 이 코드는 보통 특정 Uber 서비스 센터 또는 운영 지역을 나타냅니다.
count
564516.000000
564516.000000
mean
40.740005
-73.976817
std
0.036083
0.050426
min
40.072900
-74.773300
25%
40.722500
-73.997700
50%
40.742500
-73.984800
75%
40.760700
-73.970000
max
42.116600
-72.066600
1. 데이터의 기본적인 indexing 및 slicing
0
4/1/2014 0:11:00
40.7690
-73.9549
B02512
1
4/1/2014 0:17:00
40.7267
-74.0345
B02512
2
4/1/2014 0:21:00
40.7316
-73.9873
B02512
3
4/1/2014 0:28:00
40.7588
-73.9776
B02512
4
4/1/2014 0:33:00
40.7594
-73.9722
B02512
# 'Lat' 열의 값만 출력
df['Lat' ]
0 40.7690
1 40.7267
2 40.7316
3 40.7588
4 40.7594
...
564511 40.7640
564512 40.7629
564513 40.7443
564514 40.6756
564515 40.6880
Name: Lat, Length: 564516, dtype: float64
# 10행부터 20행까지 출력
df.iloc[10 :21 ]
10
4/1/2014 1:19:00
40.7256
-73.9869
B02512
11
4/1/2014 1:48:00
40.7591
-73.9684
B02512
12
4/1/2014 1:49:00
40.7271
-73.9803
B02512
13
4/1/2014 2:11:00
40.6463
-73.7896
B02512
14
4/1/2014 2:25:00
40.7564
-73.9167
B02512
15
4/1/2014 2:31:00
40.7666
-73.9531
B02512
16
4/1/2014 2:43:00
40.7580
-73.9761
B02512
17
4/1/2014 3:22:00
40.7238
-73.9821
B02512
18
4/1/2014 3:35:00
40.7531
-74.0039
B02512
19
4/1/2014 3:35:00
40.7389
-74.0393
B02512
20
4/1/2014 3:41:00
40.7619
-73.9715
B02512
# Base 갯수 확인
df['Base' ].value_counts()
Base
B02682 227808
B02598 183263
B02617 108001
B02512 35536
B02764 9908
Name: count, dtype: int64
2. 결측치에 대한 처리
# 결측치 개수 확인
df.isnull().sum ()
Date/Time 0
Lat 0
Lon 0
Base 0
dtype: int64
3. 기초적인 통계 추출 및 분석
# 데이터 요약
print (df.describe())
# 'Lat' 열의 평균
print (df['Lat' ].mean())
# 'Lon' 열의 중앙값
print (df['Lon' ].median())
# 'Base' 열에서 각 값의 빈도수 출력
print (df['Base' ].value_counts())
Lat Lon
count 564516.000000 564516.000000
mean 40.740005 -73.976817
std 0.036083 0.050426
min 40.072900 -74.773300
25% 40.722500 -73.997700
50% 40.742500 -73.984800
75% 40.760700 -73.970000
max 42.116600 -72.066600
40.74000520746974
-73.9848
Base
B02682 227808
B02598 183263
B02617 108001
B02512 35536
B02764 9908
Name: count, dtype: int64
4. 데이터에 대한 질문을 던져보고 해답을 찾기
4.1 월별/요일별 Uber 이용량 비교
가장 Uber 이용량이 많은 요일은 언제일까요?
df['Datetime' ] = pd.to_datetime(df['Date/Time' ])
df['Weekday' ] = df['Datetime' ].dt.day_name()
weekday_count = df['Weekday' ].value_counts().to_frame().reset_index()
display(weekday_count)
print (f"Uber 이용량이 가장 많은 요일 : { weekday_count. loc[weekday_count['count' ].idxmax(), 'Weekday' ]} " )
0
Wednesday
108631
1
Tuesday
91185
2
Friday
90303
3
Thursday
85067
4
Saturday
77218
5
Monday
60861
6
Sunday
51251
Uber 이용량이 가장 많은 요일 : Wednesday
fig, ax = plt.subplots(figsize = (8 , 6 ))
sns.barplot(x = 'Weekday' , y = 'count' , ax = ax, data = weekday_count, palette = 'Set2' )
plt.title('요일별 Uber 이용량' )
plt.show()
4.2 시간대별 이용량 비교
df['Hour' ] = df['Datetime' ].dt.hour
hour_count = df['Hour' ].value_counts().to_frame().reset_index()
display(hour_count.head())
print (f"Uber 이용량이 가장 많은 시간대 : { hour_count. loc[hour_count['count' ].idxmax(), 'Hour' ]} " )
0
17
45475
1
18
43003
2
16
42003
3
19
38923
4
21
36964
fig, ax = plt.subplots(figsize = (8 , 6 ))
sns.barplot(x = 'Hour' , y = 'count' , ax = ax, data = hour_count, color = '#8BB0F5' )# palette = 'viridis')
plt.title('시간대별 Uber 이용량' )
plt.show()
4.3 Uber 수요에 대한 공간적인 시각화
가장 수요가 많은 지역은 어디일까요?
시간대/지역별로 수요의 변화를 나타내보고, 시사점을 도출해 봅시다
df['hex' ] = df.apply (lambda row : h3.geo_to_h3(row['Lat' ], row['Lon' ], 6 ), axis = 1 )
df.head()
0
4/1/2014 0:11:00
40.7690
-73.9549
B02512
2014-04-01 00:11:00
Tuesday
0
862a100d7ffffff
1
4/1/2014 0:17:00
40.7267
-74.0345
B02512
2014-04-01 00:17:00
Tuesday
0
862a1072fffffff
2
4/1/2014 0:21:00
40.7316
-73.9873
B02512
2014-04-01 00:21:00
Tuesday
0
862a100d7ffffff
3
4/1/2014 0:28:00
40.7588
-73.9776
B02512
2014-04-01 00:28:00
Tuesday
0
862a100d7ffffff
4
4/1/2014 0:33:00
40.7594
-73.9722
B02512
2014-04-01 00:33:00
Tuesday
0
862a100d7ffffff
h3_counts = Counter(df['hex' ]) # 각 셀에 포함된 데이터 개수 계산
df_h3_counts = pd.DataFrame.from_dict(h3_counts, orient = 'index' ).reset_index()
df_h3_counts.columns = ['h3' , 'count' ]
df_h3_counts['lat' ] = df_h3_counts['h3' ].apply (lambda x : h3.h3_to_geo(x)[0 ])
df_h3_counts['lon' ] = df_h3_counts['h3' ].apply (lambda x : h3.h3_to_geo(x)[1 ])
df_h3_counts.head()
0
862a100d7ffffff
247294
40.742749
-73.957628
1
862a1072fffffff
125962
40.704168
-74.016008
2
862a10727ffffff
50036
40.759208
-74.033187
3
862a103b7ffffff
11639
40.654664
-73.789791
4
862a100f7ffffff
10999
40.781318
-73.899155
# Define a layer to display on a map
layer = pdk.Layer(
'H3HexagonLayer' ,
df_h3_counts,
pickable = True ,
stroked = True ,
filled = True ,
extruded = False ,
get_hexagon = 'h3' ,
get_fill_color = '[255 - count, 255, count]' ,
get_line_color = [255 , 255 , 255 ],
line_width_min_pixels = 2 ,
)
# Set the viewport location
view_state = pdk.ViewState(latitude = 40.7425 , longitude = - 73.9848 ,
zoom = 8 , bearing = 0 , pitch = 30 )
# Render
r = pdk.Deck(layers = [layer], initial_view_state = view_state, tooltip = {'text' : 'Count: {count} ' })
r.show()